package com.lagou.rpc.netty;

import com.lagou.rpc.handler.RpcClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.concurrent.*;

/**
 * @ClassName RpcClinetBootStrap
 * @Description
 * @Author playboy
 * @Date 2021/6/5 4:04 下午
 * @Version 1.0
 **/
@Component
@Scope("prototype")
public class RpcClinetChannelHolder {

	@Autowired
	private RpcClientHandler rpcClientHandler;

	private InetSocketAddress inetSocketAddress;

	private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
			10,
			10,
			1000L,
			TimeUnit.SECONDS,
			new ArrayBlockingQueue<Runnable>(10),
			Executors.defaultThreadFactory(),
			new ThreadPoolExecutor.AbortPolicy()
	);

	public void setInetSocketAddress(InetSocketAddress inetSocketAddress) {
		this.inetSocketAddress = inetSocketAddress;
	}

	public InetSocketAddress getInetSocketAddress() {
		return inetSocketAddress;
	}

	NioEventLoopGroup eventLoopGroup = null;
	Channel channel = null;

	public void init() {
		try {
			eventLoopGroup = new NioEventLoopGroup();
			Bootstrap bootstrap = new Bootstrap();
			bootstrap.group(eventLoopGroup)
					.channel(NioSocketChannel.class)
					.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
					.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
					.handler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel socketChannel) throws Exception {
							ChannelPipeline pipeline = socketChannel.pipeline();
							pipeline.addLast(new StringDecoder());
							pipeline.addLast(new StringEncoder());
							pipeline.addLast(rpcClientHandler);
						}
					});
			channel = bootstrap.connect(inetSocketAddress).sync().channel();
			System.out.println("连接建立，channel=" + channel);
		} catch (Exception e) {
			e.printStackTrace();
			close();
		}
	}

	public String send(String requestMsg) throws ExecutionException, InterruptedException {
		rpcClientHandler.setRequestMsg(requestMsg);
		Future<String> future = threadPoolExecutor.submit(rpcClientHandler);
		return future.get();
	}

	public void close() {
		if (channel != null) {
			channel.close();
		}
		if (eventLoopGroup != null) {
			eventLoopGroup.shutdownGracefully();
		}
	}
}
